use crate::chat::JsonObject;
use serde::{Deserialize, Serialize};

/// Represents a list of Response items.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResponseItemList {
    /// A list of items used to generate this response.
    pub data: Vec<ResponseItem>,
    /// The ID of the first item in the list.
    pub first_id: String,
    /// Whether there are more items available.
    pub has_more: bool,
    /// The ID of the last item in the list.
    pub last_id: String,
    /// The type of object returned, must be `list`.
    pub object: String,
}

#[test]
fn test_list_input_items() {
    let items = ResponseItemList {
        object: "list".to_string(),
        data: vec![ResponseItem::InputMessage {
            id: "msg_abc123".to_string(),
            role: "user".to_string(),
            status: None,
            ty: "message".to_string(),
            content: vec![ResponseItemInputMessageContent::Text {
                text: "Hello, world!".to_string(),
                ty: "input_text".to_string(),
            }],
        }],
        first_id: "msg_abc123".to_string(),
        last_id: "msg_abc123".to_string(),
        has_more: false,
    };

    let actual = serde_json::to_string_pretty(&items).unwrap();
    let expected = r#"{
  "data": [
    {
      "content": [
        {
          "text": "Hello, world!",
          "type": "input_text"
        }
      ],
      "id": "msg_abc123",
      "role": "user",
      "type": "message"
    }
  ],
  "first_id": "msg_abc123",
  "has_more": false,
  "last_id": "msg_abc123",
  "object": "list"
}"#;
    assert_eq!(actual, expected);
}

/// Represents the type of an item content used to generate a response.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ResponseItem {
    /// A message input to the model with a role indicating instruction following hierarchy. Instructions given with the `developer` or `system` role take precedence over instructions given with the `user` role.
    InputMessage {
        /// A list of one or many input items to the model, containing different content types.
        content: Vec<ResponseItemInputMessageContent>,
        /// The unique ID of the message input.
        id: String,
        /// The role of the message input. One of `user`, `system`, or `developer`.
        role: String,
        /// The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API.
        #[serde(skip_serializing_if = "Option::is_none")]
        status: Option<String>,
        /// The type of the message input. Always set to `message`.
        #[serde(rename = "type")]
        ty: String,
    },
    /// An output message from the model.
    OutputMessage {
        /// The content of the output message.
        content: Vec<ResponseItemOutputMessageContent>,
        /// The unique ID of the output message.
        id: String,
        /// The role of the output message. Always `assistant`.
        role: String,
        /// The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API.
        status: String,
        /// The type of the message input. Always set to `message`.
        #[serde(rename = "type")]
        ty: String,
    },
    /// A tool call to run a function.
    FunctionCall {
        /// A JSON string of the arguments to pass to the function.
        arguments: String,
        /// The unique ID of the function tool call generated by the model.
        call_id: String,
        /// The unique ID of the function tool call.
        id: String,
        /// The name of the function to run.
        name: String,
        /// The type of the function tool call. Always `function_call`.
        #[serde(rename = "type")]
        ty: String,
        /// The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API.
        status: String,
    },
    /// The output of a function tool call.
    FunctionCallOutput {
        /// The unique ID of the function tool call generated by the model.
        call_id: String,
        /// The unique ID of the function call tool output.
        id: String,
        /// A JSON string of the output of the function tool call.
        output: String,
        /// The type of the function tool call output. Always `function_call_output`.
        #[serde(rename = "type")]
        ty: String,
        /// The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API.
        status: String,
    },
    /// An image generation request made by the model.
    ImageGeneration {
        /// The unique ID of the image generation call.
        id: String,
        /// The generated image encoded in base64.
        result: String,
        /// The status of the image generation call.
        status: String,
        /// The type of the image generation call. Always `image_generation_call`.
        #[serde(rename = "type")]
        ty: String,
    },
    /// A list of tools available on an MCP server.
    McpListTools {
        /// The unique ID of the list.
        id: String,
        /// The label of the MCP server.
        server_label: String,
        /// The tools available on the server.
        tools: Vec<McpTool>,
        /// The type of the item. Always `mcp_list_tools`.
        #[serde(rename = "type")]
        ty: String,
        /// Error message if the server could not list tools.
        error: String,
    },
    /// An invocation of a tool on an MCP server.
    McpToolCall {
        /// A JSON string of the arguments passed to the tool.
        arguments: String,
        /// The unique ID of the tool call.
        id: String,
        /// The name of the tool that was run.
        name: String,
        /// The label of the MCP server running the tool.
        server_label: String,
        /// The type of the item. Always `mcp_call`.
        #[serde(rename = "type")]
        ty: String,
        /// The error from the tool call, if any.
        error: String,
        /// The output from the tool call.
        output: String,
    },
}

#[test]
fn test_input_item() {
    let item = ResponseItem::InputMessage {
        id: "msg_abc123".to_string(),
        role: "user".to_string(),
        status: None,
        ty: "message".to_string(),
        content: vec![ResponseItemInputMessageContent::Text {
            text: "Hello, world!".to_string(),
            ty: "input_text".to_string(),
        }],
    };

    let actual = serde_json::to_string_pretty(&item).unwrap();
    let expected = r#"{
  "content": [
    {
      "text": "Hello, world!",
      "type": "input_text"
    }
  ],
  "id": "msg_abc123",
  "role": "user",
  "type": "message"
}"#;
    assert_eq!(actual, expected);
}

/// Represents the type of the item content generated by the model.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ResponseOutputItem {
    /// An output message from the model.
    OutputMessage {
        /// The content of the output message.
        content: Vec<ResponseOutputItemOutputMessageContent>,
        /// The unique ID of the output message.
        id: String,
        /// The role of the output message. Always `assistant`.
        role: String,
        /// The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API.
        status: String,
        /// The type of the output message. Always `message`.
        #[serde(rename = "type")]
        ty: String,
    },
    /// A tool call to run a function.
    FunctionCall {
        /// A JSON string of the arguments to pass to the function.
        arguments: String,
        /// The unique ID of the function tool call generated by the model.
        call_id: String,
        /// The unique ID of the function tool call.
        id: String,
        /// The name of the function to run.
        name: String,
        /// The type of the function tool call. Always `function_call`.
        #[serde(rename = "type")]
        ty: String,
        /// The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API.
        status: String,
    },
    /// An image generation request made by the model.
    ImageGeneration {
        /// The unique ID of the image generation call.
        id: String,
        /// The generated image encoded in base64.
        result: String,
        /// The status of the image generation call.
        status: String,
        /// The type of the image generation call. Always `image_generation_call`.
        #[serde(rename = "type")]
        ty: String,
    },
    /// An invocation of a tool on an MCP server.
    McpToolCall {
        /// A JSON string of the arguments passed to the tool.
        arguments: String,
        /// The unique ID of the tool call.
        id: String,
        /// The name of the tool that was run.
        name: String,
        /// The label of the MCP server running the tool.
        server_label: String,
        /// The type of the item. Always `mcp_call`.
        #[serde(rename = "type")]
        ty: String,
        /// The error from the tool call, if any.
        error: String,
        /// The output from the tool call.
        output: String,
    },
    /// A list of tools available on an MCP server.
    McpListTools {
        /// The unique ID of the list.
        id: String,
        /// The label of the MCP server.
        server_label: String,
        /// The tools available on the server.
        tools: Vec<McpTool>,
        /// The type of the item. Always `mcp_list_tools`.
        #[serde(rename = "type")]
        ty: String,
        /// Error message if the server could not list tools.
        error: String,
    },
}

/// Represents the content of an input message to the model, containing different content types.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ResponseItemInputMessageContent {
    /// A text input to the model.
    Text {
        /// The text input to the model.
        text: String,
        /// The type of the input item. Always `input_text`.
        #[serde(rename = "type")]
        ty: String,
    },
    /// An image input to the model.
    Image {
        /// The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`.
        detail: String,
        /// The type of the input item. Always `input_image`.
        #[serde(rename = "type")]
        ty: String,
        /// The ID of the file to be sent to the model.
        file_id: String,
        /// The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL.
        image_url: String,
    },
    /// A file input to the model.
    File {
        /// The type of the input item. Always `input_file`.
        #[serde(rename = "type")]
        ty: String,
        /// The content of the file to be sent to the model.
        file_data: String,
        /// The ID of the file to be sent to the model.
        file_id: String,
        /// The URL of the file to be sent to the model.
        file_url: String,
        /// The name of the file to be sent to the model.
        filename: String,
    },
    /// An audio input to the model.
    Audio {
        input_audio: InputAudio,
        /// The type of the input item. Always `input_audio`.
        #[serde(rename = "type")]
        ty: String,
    },
}

/// Represents an audio input to the model.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InputAudio {
    /// Base64-encoded audio data.
    data: String,
    /// The format of the audio data. Currently supported formats are `mp3` and `wav`.
    format: String,
}

/// Represents the content of an output message from the model, containing different content types.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
pub enum ResponseItemOutputMessageContent {
    /// Text content type
    Text {
        /// The text output from the model.
        text: String,
        /// The annotations of the text output.
        annotations: Vec<Annotation>,
    },
    /// Refusal content type (when model refuses to answer)
    Refusal { refusal: String },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ResponseOutputItemOutputMessageContent {
    /// A text output from the model.
    OutputText {
        annotations: Vec<Annotation>,
        text: String,
        #[serde(rename = "type")]
        ty: String,
        #[serde(skip_serializing_if = "Option::is_none")]
        logprobs: Option<Vec<LogProb>>,
    },
    /// A refusal from the model to answer.
    Refusal {
        refusal: String,
        #[serde(rename = "type")]
        ty: String,
    },
}

/// Log probability information for the choice.
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct LogProb {
    pub bytes: Vec<u8>,
    pub logprob: f64,
    pub token: String,
    pub top_logprobs: Vec<TopLogProb>,
}

/// Represents the top log probabilities for tokens.
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct TopLogProb {
    pub bytes: Vec<u8>,
    pub logprob: f64,
    pub token: String,
}

/// Represents annotation information of the text output.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
pub enum Annotation {
    /// A citation to a file.
    FileCitation {
        /// The ID of the file.
        #[serde(rename = "file_id")]
        id: String,
        /// The filename of the file cited.
        filename: String,
        /// The index of the file in the list of files.
        index: usize,
        /// The type of the file citation. Always `file_citation`.
        #[serde(rename = "type")]
        ty: String,
    },
    /// A citation for a web resource used to generate a model response.
    UrlCitation {
        /// The index of the last character of the URL citation in the message.
        end_index: usize,
        /// The index of the first character of the URL citation in the message.
        start_index: usize,
        /// The title of the web resource.
        title: String,
        /// The type of the URL citation. Always `url_citation`.
        #[serde(rename = "type")]
        ty: String,
        /// The URL of the web resource.
        url: String,
    },
    /// Container file citation annotation
    ContainerFileCitation {
        /// The ID of the container file.
        container_id: String,
        /// The index of the last character of the container file citation in the message.
        end_index: usize,
        /// The ID of the file.
        #[serde(rename = "file_id")]
        id: String,
        /// The filename of the container file cited.
        filename: String,
        /// The index of the first character of the container file citation in the message.
        start_index: usize,
        /// The type of the container file citation. Always `container_file_citation`.
        #[serde(rename = "type")]
        ty: String,
    },
    /// A path to a file.
    FilePath {
        /// The ID of the file.
        #[serde(rename = "file_id")]
        id: String,
        /// The index of the file in the list of files.
        index: usize,
        /// The type of the file path. Always `file_path`.
        #[serde(rename = "type")]
        ty: String,
    },
}

/// Represents an MCP tool available on an MCP server.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct McpTool {
    /// The JSON schema describing the tool's input.
    pub input_schema: JsonObject,
    /// The name of the tool.
    pub name: String,
    /// Additional annotations about the tool.
    pub annotations: Option<Annotation>,
    /// The description of the tool.
    pub description: String,
}

#[test]
fn test_annotation_file_citation_serialization() {
    let annotation = Annotation::FileCitation {
        id: "file_123".to_string(),
        filename: "document.pdf".to_string(),
        index: 0,
        ty: "file_citation".to_string(),
    };

    let serialized = serde_json::to_string_pretty(&annotation).unwrap();
    let expected = r#"{
  "file_id": "file_123",
  "filename": "document.pdf",
  "index": 0,
  "type": "file_citation"
}"#;
    assert_eq!(serialized, expected);

    // Test deserialization
    let deserialized: Annotation = serde_json::from_str(&serialized).unwrap();
    assert_eq!(annotation, deserialized);
}

#[test]
fn test_annotation_url_citation_serialization() {
    let annotation = Annotation::UrlCitation {
        end_index: 45,
        start_index: 10,
        title: "OpenAI API Documentation".to_string(),
        ty: "url_citation".to_string(),
        url: "https://platform.openai.com/docs".to_string(),
    };

    let serialized = serde_json::to_string_pretty(&annotation).unwrap();
    let expected = r#"{
  "end_index": 45,
  "start_index": 10,
  "title": "OpenAI API Documentation",
  "type": "url_citation",
  "url": "https://platform.openai.com/docs"
}"#;
    assert_eq!(serialized, expected);

    // Test deserialization
    let deserialized: Annotation = serde_json::from_str(&serialized).unwrap();
    assert_eq!(annotation, deserialized);
}

#[test]
fn test_annotation_container_file_citation_serialization() {
    let annotation = Annotation::ContainerFileCitation {
        container_id: "container_456".to_string(),
        end_index: 120,
        id: "file_789".to_string(),
        filename: "archive.zip".to_string(),
        start_index: 80,
        ty: "container_file_citation".to_string(),
    };

    let serialized = serde_json::to_string_pretty(&annotation).unwrap();
    let expected = r#"{
  "container_id": "container_456",
  "end_index": 120,
  "file_id": "file_789",
  "filename": "archive.zip",
  "start_index": 80,
  "type": "container_file_citation"
}"#;
    assert_eq!(serialized, expected);

    // Test deserialization
    let deserialized: Annotation = serde_json::from_str(&serialized).unwrap();
    assert_eq!(annotation, deserialized);
}

#[test]
fn test_annotation_file_path_serialization() {
    let annotation = Annotation::FilePath {
        id: "file_321".to_string(),
        index: 2,
        ty: "file_path".to_string(),
    };

    let serialized = serde_json::to_string_pretty(&annotation).unwrap();
    let expected = r#"{
  "file_id": "file_321",
  "index": 2,
  "type": "file_path"
}"#;
    assert_eq!(serialized, expected);

    // Test deserialization
    let deserialized: Annotation = serde_json::from_str(&serialized).unwrap();
    assert_eq!(annotation, deserialized);
}

#[test]
fn test_response_item_list_deserialization() {
    // Test deserialization of the specific JSON provided by the user
    let json = r#"{
  "object": "list",
  "data": [
    {
      "id": "msg_abc123",
      "type": "message",
      "role": "user",
      "content": [
        {
          "type": "input_text",
          "text": "Tell me a three sentence bedtime story about a unicorn."
        }
      ]
    }
  ],
  "first_id": "msg_abc123",
  "last_id": "msg_abc123",
  "has_more": false
}"#;

    // Test deserialization
    let result: Result<ResponseItemList, _> = serde_json::from_str(json);

    match result {
        Ok(item_list) => {
            // Verify top-level fields
            assert_eq!(item_list.object, "list");
            assert_eq!(item_list.first_id, "msg_abc123");
            assert_eq!(item_list.last_id, "msg_abc123");
            assert_eq!(item_list.has_more, false);
            assert_eq!(item_list.data.len(), 1);

            // Verify the single data item
            match &item_list.data[0] {
                ResponseItem::InputMessage {
                    id,
                    role,
                    ty,
                    content,
                    status,
                } => {
                    assert_eq!(id, "msg_abc123");
                    assert_eq!(role, "user");
                    assert_eq!(ty, "message");
                    assert!(status.is_none()); // status should be None since it's not in JSON
                    assert_eq!(content.len(), 1);

                    // Verify the content
                    match &content[0] {
                        ResponseItemInputMessageContent::Text { text, ty } => {
                            assert_eq!(
                                text,
                                "Tell me a three sentence bedtime story about a unicorn."
                            );
                            assert_eq!(ty, "input_text");
                        }
                        _ => panic!("Expected Text variant in content"),
                    }
                }
                _ => panic!("Expected InputMessage variant in data"),
            }

            // Test serialization roundtrip
            let serialized = serde_json::to_string_pretty(&item_list).unwrap();
            println!("Serialized ResponseItemList:\n{}", serialized);

            let re_deserialized: ResponseItemList = serde_json::from_str(&serialized).unwrap();

            // Verify roundtrip preserves key data
            assert_eq!(item_list.object, re_deserialized.object);
            assert_eq!(item_list.first_id, re_deserialized.first_id);
            assert_eq!(item_list.last_id, re_deserialized.last_id);
            assert_eq!(item_list.has_more, re_deserialized.has_more);
            assert_eq!(item_list.data.len(), re_deserialized.data.len());

            // Verify the data item after roundtrip
            match (&item_list.data[0], &re_deserialized.data[0]) {
                (
                    ResponseItem::InputMessage {
                        id: id1,
                        role: role1,
                        ty: ty1,
                        content: content1,
                        ..
                    },
                    ResponseItem::InputMessage {
                        id: id2,
                        role: role2,
                        ty: ty2,
                        content: content2,
                        ..
                    },
                ) => {
                    assert_eq!(id1, id2);
                    assert_eq!(role1, role2);
                    assert_eq!(ty1, ty2);
                    assert_eq!(content1.len(), content2.len());

                    match (&content1[0], &content2[0]) {
                        (
                            ResponseItemInputMessageContent::Text {
                                text: text1,
                                ty: ty1,
                            },
                            ResponseItemInputMessageContent::Text {
                                text: text2,
                                ty: ty2,
                            },
                        ) => {
                            assert_eq!(text1, text2);
                            assert_eq!(ty1, ty2);
                        }
                        _ => panic!("Expected Text variants in both contents"),
                    }
                }
                _ => panic!("Expected InputMessage variants in both data items"),
            }

            println!(
                "✅ ResponseItemList bedtime story deserialization and serialization successful!"
            );
        }
        Err(e) => {
            println!("❌ ResponseItemList deserialization failed: {}", e);
            panic!("Expected deserialization to succeed, but got error: {}", e);
        }
    }
}

#[test]
fn test_response_output_item_output_message_content_output_text_serialization() {
    let content = ResponseOutputItemOutputMessageContent::OutputText {
        annotations: vec![Annotation::FileCitation {
            id: "file_123".to_string(),
            filename: "document.pdf".to_string(),
            index: 0,
            ty: "file_citation".to_string(),
        }],
        text: "This is the output text from the model.".to_string(),
        ty: "output_text".to_string(),
        logprobs: None,
    };

    let serialized = serde_json::to_string_pretty(&content).unwrap();
    let expected = r#"{
  "annotations": [
    {
      "file_id": "file_123",
      "filename": "document.pdf",
      "index": 0,
      "type": "file_citation"
    }
  ],
  "text": "This is the output text from the model.",
  "type": "output_text"
}"#;
    assert_eq!(serialized, expected);

    // Test deserialization
    let deserialized: ResponseOutputItemOutputMessageContent =
        serde_json::from_str(&serialized).unwrap();

    match deserialized {
        ResponseOutputItemOutputMessageContent::OutputText {
            text,
            annotations,
            ty,
            logprobs,
        } => {
            assert_eq!(text, "This is the output text from the model.");
            assert_eq!(ty, "output_text");
            assert_eq!(annotations.len(), 1);
            assert!(logprobs.is_none());

            match &annotations[0] {
                Annotation::FileCitation {
                    id,
                    filename,
                    index,
                    ty,
                } => {
                    assert_eq!(id, "file_123");
                    assert_eq!(filename, "document.pdf");
                    assert_eq!(*index, 0);
                    assert_eq!(ty, "file_citation");
                }
                _ => panic!("Expected FileCitation annotation"),
            }
        }
        _ => panic!("Expected OutputText variant"),
    }

    println!("✅ ResponseOutputItemOutputMessageContent OutputText serialization test passed!");
}

#[test]
fn test_response_output_item_output_message_content_refusal_serialization() {
    let content = ResponseOutputItemOutputMessageContent::Refusal {
        refusal: "I cannot answer this question as it violates our usage policies.".to_string(),
        ty: "refusal".to_string(),
    };

    let serialized = serde_json::to_string_pretty(&content).unwrap();
    let expected = r#"{
  "refusal": "I cannot answer this question as it violates our usage policies.",
  "type": "refusal"
}"#;
    assert_eq!(serialized, expected);

    // Test deserialization
    let deserialized: ResponseOutputItemOutputMessageContent =
        serde_json::from_str(&serialized).unwrap();

    match deserialized {
        ResponseOutputItemOutputMessageContent::Refusal { refusal, ty } => {
            assert_eq!(
                refusal,
                "I cannot answer this question as it violates our usage policies."
            );
            assert_eq!(ty, "refusal");
        }
        _ => panic!("Expected Refusal variant"),
    }

    println!("✅ ResponseOutputItemOutputMessageContent Refusal serialization test passed!");
}

#[test]
fn test_response_output_item_output_message_content_with_multiple_annotations() {
    let content = ResponseOutputItemOutputMessageContent::OutputText {
        annotations: vec![
            Annotation::UrlCitation {
                end_index: 45,
                start_index: 10,
                title: "OpenAI Documentation".to_string(),
                ty: "url_citation".to_string(),
                url: "https://platform.openai.com/docs".to_string(),
            },
            Annotation::FilePath {
                id: "file_456".to_string(),
                index: 1,
                ty: "file_path".to_string(),
            },
        ],
        text: "Here is some information with citations and file references.".to_string(),
        ty: "output_text".to_string(),
        logprobs: None,
    };

    let serialized = serde_json::to_string_pretty(&content).unwrap();

    // Test deserialization
    let deserialized: ResponseOutputItemOutputMessageContent =
        serde_json::from_str(&serialized).unwrap();

    match deserialized {
        ResponseOutputItemOutputMessageContent::OutputText {
            text,
            annotations,
            ty,
            logprobs,
        } => {
            assert_eq!(
                text,
                "Here is some information with citations and file references."
            );
            assert_eq!(ty, "output_text");
            assert_eq!(annotations.len(), 2);
            assert!(logprobs.is_none());

            // Verify first annotation (UrlCitation)
            match &annotations[0] {
                Annotation::UrlCitation { title, url, .. } => {
                    assert_eq!(title, "OpenAI Documentation");
                    assert_eq!(url, "https://platform.openai.com/docs");
                }
                _ => panic!("Expected UrlCitation annotation"),
            }

            // Verify second annotation (FilePath)
            match &annotations[1] {
                Annotation::FilePath { id, index, .. } => {
                    assert_eq!(id, "file_456");
                    assert_eq!(*index, 1);
                }
                _ => panic!("Expected FilePath annotation"),
            }
        }
        _ => panic!("Expected OutputText variant"),
    }

    println!("✅ ResponseOutputItemOutputMessageContent with multiple annotations test passed!");
}

#[test]
fn test_response_output_item_output_message_content_deserialization_from_json() {
    // Test deserialization of OutputText from JSON
    let json = r#"{
  "type": "output_text",
  "text": "The capital of France is Paris.",
  "annotations": [],
  "logprobs": []
}"#;

    let result: Result<ResponseOutputItemOutputMessageContent, _> = serde_json::from_str(json);

    match result {
        Ok(ResponseOutputItemOutputMessageContent::OutputText {
            text,
            ty,
            annotations,
            logprobs,
        }) => {
            assert_eq!(text, "The capital of France is Paris.");
            assert_eq!(ty, "output_text");
            assert_eq!(annotations.len(), 0);
            assert!(logprobs.is_some() && logprobs.unwrap().is_empty());
        }
        Ok(_) => panic!("Expected OutputText variant"),
        Err(e) => panic!("Deserialization failed: {}", e),
    }

    // Test deserialization of Refusal from JSON
    let json_refusal = r#"{
  "type": "refusal",
  "refusal": "I'm sorry, but I can't assist with that request."
}"#;

    let result_refusal: Result<ResponseOutputItemOutputMessageContent, _> =
        serde_json::from_str(json_refusal);

    match result_refusal {
        Ok(ResponseOutputItemOutputMessageContent::Refusal { refusal, ty }) => {
            assert_eq!(refusal, "I'm sorry, but I can't assist with that request.");
            assert_eq!(ty, "refusal");
        }
        Ok(_) => panic!("Expected Refusal variant"),
        Err(e) => panic!("Deserialization failed: {}", e),
    }

    println!("✅ ResponseOutputItemOutputMessageContent JSON deserialization test passed!");
}
